package com.ourteam.scm.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.lib.BatchingProgressMonitor;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;

import com.hazelcast.monitor.LocalGCStats;
import com.ourteam.scm.utils.ResourceDiffentInfomation.DiffDetail;
import com.ourteam.sourcecode.utils.SourceLineBean;
import com.ourteam.sourcecode.utils.SourceLineCounter;

public class GitServiceImpl extends AbstractSCMService {

	public GitServiceImpl(SCMServerBean scmServerBean) {
		super(scmServerBean);

	}

	@Override
	public void relocateResource(String from, String to, File rootDir, ModuleInfoBean moduleInfo,
			ISCMListener scmListener) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void switchTo(File rootDir, String svnUrl, ModuleInfoBean moduleInfo, ISCMListener scmListener)
			throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void importResource(File rootDir, ModuleInfoBean moduleInfo, ISCMListener scmListener) throws Exception {
		checkoutResource(rootDir, moduleInfo, scmListener);
	}

	@Override
	public void checkoutResource(File rootDir, ModuleInfoBean moduleInfo, ISCMListener scmListener) throws Exception {

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		SCMServerBean scmServerBean = getScmServerBean();

		CredentialsProvider allowHosts = new CredentialsProvider() {

			@Override
			public boolean supports(CredentialItem... items) {
				for (CredentialItem item : items) {
					if ((item instanceof CredentialItem.YesNoType)) {
						return true;
					}
				}
				return false;
			}

			@Override
			public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
				for (CredentialItem item : items) {
					if (item instanceof CredentialItem.YesNoType) {
						((CredentialItem.YesNoType) item).setValue(true);
						return true;
					}
				}
				return false;
			}

			@Override
			public boolean isInteractive() {
				return false;
			}
		};

		String REMOTE_URL = getGitUrl(moduleInfo);

		scmListener.logCommandLine("git clone " + REMOTE_URL);

		scmListener.logMessage("Cloning from " + REMOTE_URL + " to " + rootDir.getPath());

		try (Git result = Git.cloneRepository().setURI(REMOTE_URL).setDirectory(rootDir)
				.setProgressMonitor(listenerAdapter)
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(scmServerBean.getUser(), scmServerBean.getPassword()))
				.call()) {
			// Note: the call() returns an opened repository already which needs to be
			// closed to avoid file handle leaks!
			scmListener.logMessage("Having repository: " + result.getRepository().getDirectory());
		}

		// clean up here to not keep using more and more disk-space for these samples
		// FileUtils.deleteDirectory(localPath);

	}

	@Override
	public void commitResource(File rootDir, ModuleInfoBean moduleInfo, String comment, ISCMListener scmListener)
			throws Exception {

		SCMServerBean scmServerBean = getScmServerBean();

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		Git git = Git.open(rootDir);

		git.add().addFilepattern(".").call();

		git.commit().setAll(true).setMessage(comment).call();

		git.push()
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(scmServerBean.getUser(), scmServerBean.getPassword()))
				.setProgressMonitor(listenerAdapter).call();

	}

	@Override
	public void commitResource(File rootDir, File[] dirs, ModuleInfoBean moduleInfo, String comment,
			ISCMListener scmListener) throws Exception {

		SCMServerBean scmServerBean = getScmServerBean();

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		Git git = Git.open(rootDir);

		AddCommand addCommand = git.add();

		for (int i = 0; i < dirs.length; i++) {
			addCommand.addFilepattern(getFilePath(rootDir, dirs[i]));
		}

		addCommand.call();

		git.commit().setAll(true).setMessage(comment).call();

		git.push()
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(scmServerBean.getUser(), scmServerBean.getPassword()))
				.setProgressMonitor(listenerAdapter).call();

	}

	@Override
	public void updateResource(File rootDir, ModuleInfoBean moduleInfo, ISCMListener scmListener) throws Exception {

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		SCMServerBean scmServerBean = getScmServerBean();

		Git git = Git.open(rootDir);

		git.pull()
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(scmServerBean.getUser(), scmServerBean.getPassword()))
				.setRemote("origin").call();

		FetchResult result = git.fetch()
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(scmServerBean.getUser(), scmServerBean.getPassword()))
				.setProgressMonitor(listenerAdapter).setCheckFetchedObjects(true).call();

		scmListener.logCompleted(result.getMessages());
	}

	@Override
	public void removeResource(File rootDir, File[] files, ModuleInfoBean moduleInfo, String comment,
			ISCMListener scmListener) throws Exception {

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		SCMServerBean scmServerBean = getScmServerBean();

		for (int i = 0; i < files.length; i++) {
			FileUtils.deleteQuietly(files[i]);
		}

		Git git = Git.open(rootDir);

		git.add().setUpdate(true).addFilepattern(".").call();

	}

	@Override
	public void updateResourceToVersion(File rootDir, File file, ResourceUpdateInfo versionInfo,
			ModuleInfoBean moduleInfo, ISCMListener scmListener) throws Exception {

		GITListenerAdapter listenerAdapter = new GITListenerAdapter(scmListener);

		Git git = Git.open(rootDir);

		git.checkout().addPath(getFilePath(rootDir, file)).setProgressMonitor(listenerAdapter)
				.setStartPoint(versionInfo.getRevision()).call();

		CommitCommand commitCmd = git.commit();
		commitCmd.setOnly(getFilePath(rootDir, file));
		commitCmd.setMessage(" update to " + versionInfo.getRevision()).call();

	}

	@Override
	public VersionLogInformation[] showResourceLog(File rootDir, File[] files, ModuleInfoBean moduleInfo,
			ShowResourceLogConfig[] resourceLogConfigs, String startRevision, String endRevision,
			boolean showFullDetail, ISCMListener scmListener) throws Exception {

		Git git = Git.open(rootDir);

		Repository repository = git.getRepository();

		LogCommand logCommand = git.log();

		if (StringUtils.isNoneBlank(startRevision) && StringUtils.isNoneBlank(endRevision)) {
			logCommand.addRange(repository.resolve(startRevision), repository.resolve(endRevision));
		}

		for (int i = 0; i < files.length; i++) {
			logCommand.addPath(getFilePath(rootDir, files[i]));
		}

		Iterable<RevCommit> logs = logCommand.call();

		List<VersionLogInformation> informations = new ArrayList<>();

		for (RevCommit rev : logs) {

			VersionLogInformation information = new VersionLogInformation();

			information.setAuthor(rev.getAuthorIdent().getName());

			information.setComment(rev.getFullMessage());

			information.setRevision(rev.getName());

			information.setRevisionTime(rev.getCommitterIdent().getWhen());

			informations.add(information);

		}

		return informations.toArray(new VersionLogInformation[informations.size()]);
	}

	@Override
	public VersionLogInformation[] scanResourceLog(File rootDir, ModuleInfoBean moduleInfo,
			ShowResourceLogConfig[] resourceLogConfigs, String startRevision, String endRevision,
			ISCMListener scmListener) throws Exception {

		Git git = Git.open(rootDir);

		Repository repository = git.getRepository();

		LogCommand logCommand = git.log();

		if (StringUtils.isBlank(startRevision) && StringUtils.isBlank(endRevision)) {
			logCommand.all();
		} else {
			logCommand.addRange(repository.resolve(startRevision),
					repository.resolve(StringUtils.isNoneBlank(endRevision) ? endRevision : "HEAD"));
		}

		List<VersionLogInformation> informations = new ArrayList<>();

		Iterable<RevCommit> logs = logCommand.call();

		for (RevCommit log : logs) {

			long totalLines = 0;

			long totalFileSize = 0;

			VersionLogInformation versionLogInformation = new VersionLogInformation();

			versionLogInformation.setAuthor(log.getCommitterIdent().getName());

			versionLogInformation.setComment(log.getFullMessage());

			versionLogInformation.setRevision(log.getId().getName());

			versionLogInformation.setRevisionTime(log.getCommitterIdent().getWhen());

			TreeWalk treeWalk = new TreeWalk(repository);

			// treeWalk.addTree(new RevWalk(repository).parseTree(log.getId()));
			treeWalk.addTree(log.getTree());

			treeWalk.setRecursive(true);

			while (treeWalk.next()) {

				ObjectId objectId = treeWalk.getObjectId(0);

				ObjectLoader loader = repository.open(objectId);

				ByteArrayOutputStream out = new ByteArrayOutputStream();

				loader.copyTo(out);

				int lines = countAddLine(new String(out.toByteArray(), "UTF-8"));

				VersionLogChangePath changePath = new VersionLogChangePath();

				changePath.setPath(treeWalk.getPathString());
				changePath.setFileSize(loader.getSize());
				changePath.setCopySrcRevision(log.getId().getName());
				changePath.setLineCount(lines);

				if (log.getParentCount() > 0) {
					ObjectId newObjectId = repository.resolve(log.getId().getName() + "^{tree}");

					ObjectId oldObjectId = repository.resolve(log.getParent(0).getName() + "^{tree}");

					ObjectReader reader = git.getRepository().newObjectReader();

					CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
					oldTreeIter.reset(reader, oldObjectId);
					CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
					newTreeIter.reset(reader, newObjectId);

					List<DiffEntry> diff = git.diff().setPathFilter(PathFilter.create(treeWalk.getPathString()))
							.setOldTree(oldTreeIter).setNewTree(newTreeIter).setShowNameAndStatusOnly(true).call();

					DiffFormatter df = new DiffFormatter(out);
					// 设置比较器为忽略空白字符对比（Ignores all whitespace）
					df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
					df.setRepository(git.getRepository());
					// 每一个diffEntry都是第个文件版本之间的变动差异
					for (DiffEntry diffEntry : diff) {
						// 打印文件差异具体内容
						df.format(diffEntry);

						// 获取文件差异位置，从而统计差异的行数，如增加行数，减少行数
						FileHeader fileHeader = df.toFileHeader(diffEntry);
						List<HunkHeader> hunks = (List<HunkHeader>) fileHeader.getHunks();
						int addSize = 0;
						int subSize = 0;
						for (HunkHeader hunkHeader : hunks) {
							EditList editList = hunkHeader.toEditList();
							for (Edit edit : editList) {
								subSize += edit.getEndA() - edit.getBeginA();
								addSize += edit.getEndB() - edit.getBeginB();
							}
						}
						// System.out.println("addSize="+addSize);
						// System.out.println("subSize="+subSize);

						changePath.setChangeLineCount(addSize + subSize);
					}
				}

				totalLines = totalLines + lines;

				totalFileSize = totalFileSize + loader.getSize();

				versionLogInformation.getChangePaths().add(changePath);

//				if (logConfig != null && logConfig.isCountLine()) {
				SourceLineBean sourceLineBean = SourceLineCounter
						.parse(IOUtils.toInputStream(new String(out.toByteArray(), "UTF-8"), "UTF-8"));
				changePath.setLineCount(sourceLineBean.getCodeLines());
				changePath.setCommnetLineCount(sourceLineBean.getCommentLines());
				changePath.setBlankLineCount(sourceLineBean.getBlankLines());
//				}

			}

			versionLogInformation.setTotalLines(totalLines);
			versionLogInformation.setTotalSize(totalFileSize);

			informations.add(versionLogInformation);

		}

		return informations.toArray(new VersionLogInformation[informations.size()]);

	}

	public AbstractTreeIterator prepareTreeParser(Repository repository, RevCommit commit) {
		System.out.println(commit.getId());
		try (RevWalk walk = new RevWalk(repository)) {
			// System.out.println(commit.getTree().getId());
			RevTree tree = walk.parseTree(commit.getTree().getId());

			CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
			try (ObjectReader oldReader = repository.newObjectReader()) {
				oldTreeParser.reset(oldReader, tree.getId());
			}

			walk.dispose();

			return oldTreeParser;
		} catch (Exception e) {
		}
		return null;
	}

	private int countAddLine(String content) {
		char[] chars = content.toCharArray();
		int sum = 0;
		boolean notSpace = false;
		for (char ch : chars) {
			if (ch == '\n' && notSpace) {
				sum++;
				notSpace = false;
			} else if (ch > ' ') {
				notSpace = true;
			}
		}
		// 最后一行没有换行时，如果有非空白字符，则+1
		if (notSpace) {
			sum++;
		}
		return sum;
	}

	@Override
	public ResourceDiffentInfomation showResourceDiffent(File rootDir, File file, String leftVersion,
			String rightVersion, ModuleInfoBean moduleInfo, ISCMListener scmListener) throws Exception {

		Git git = Git.open(rootDir);

		Repository repository = git.getRepository();

		ObjectId newObjectId = repository.resolve(rightVersion + "^{tree}");

		ObjectId oldObjectId = repository.resolve(leftVersion + "^{tree}");

		ObjectReader reader = git.getRepository().newObjectReader();

		CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
		oldTreeIter.reset(reader, oldObjectId);
		CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
		newTreeIter.reset(reader, newObjectId);

		// ObjectLoader newObjLoader = repository.open(newObjectId);

		// ObjectLoader oldObjLoader = repository.open(oldObjectId);

		List<DiffEntry> diff = git.diff().setPathFilter(PathFilter.create(getFilePath(rootDir, file)))
				.setOldTree(oldTreeIter).setNewTree(newTreeIter).call();

		StringBuffer diffContent = new StringBuffer();

		ResourceDiffentInfomation diffentInfomation = new ResourceDiffentInfomation();

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		DiffFormatter df = new DiffFormatter(out);
		df.setRepository(git.getRepository());

		for (DiffEntry entry : diff) {

			df.format(entry);
			String diffText = out.toString("UTF-8");
			// System.out.println(diffText);
			diffContent.append(diffText);
			out.reset();
		}

		diffentInfomation.setLeftVersion(leftVersion);
		diffentInfomation.setRightVersion(rightVersion);
		diffentInfomation.setDiffOutput(diffContent.toString());
		diffentInfomation.setFileName(FilenameUtils.getName(file.getName()));
		diffentInfomation.setFileType(FilenameUtils.getExtension(file.getName()));
		diffentInfomation.setLeftContent(read(getFilePath(rootDir, file), leftVersion, git).toString("utf8"));
		diffentInfomation.setRightContent(read(getFilePath(rootDir, file), rightVersion, git).toString("utf8"));

		List<DiffDetail> leftDiffDetails = new ArrayList<DiffDetail>();

		List<DiffDetail> rightDiffDetails = new ArrayList<DiffDetail>();

		List<String> diffLines = IOUtils.readLines(new StringReader(diffentInfomation.getDiffOutput()));

		List<String> leftContents = IOUtils.readLines(new StringReader(diffentInfomation.getLeftContent()));

		List<String> rightContents = IOUtils.readLines(new StringReader(diffentInfomation.getRightContent()));
		// @@ -29,13 +29,4 @@
		for (Iterator<String> iterator = diffLines.iterator(); iterator.hasNext();) {
			String line = iterator.next();
			if (StringUtils.startsWith(line, "@@") && StringUtils.endsWith(line, "@@")) { // left

				String diffLinStr = StringUtils.trim(StringUtils.substringBetween(line, "@@"));

				String[] diffLins = StringUtils.split(diffLinStr, " ");

				String[] leftRow = StringUtils.split(diffLins[0], ",");

				String[] rightRow = StringUtils.split(diffLins[1], ",");

				int start = Math.abs(Integer.parseInt(leftRow[0]));

				int end = start + Integer.parseInt(leftRow[1]);

				for (int i = start; i < end; i++) {
					DiffDetail leftDiffDetail = new DiffDetail();
					leftDiffDetail.setContent(leftContents.get(i - 1));
					leftDiffDetail.setLineNumber(i);
					leftDiffDetail.setType(1);
					leftDiffDetails.add(leftDiffDetail);
				}

				start = Math.abs(Integer.parseInt(rightRow[0]));

				end = start + Integer.parseInt(rightRow[1]);

				for (int i = start; i < end; i++) {
					DiffDetail rightDiffDetail = new DiffDetail();
					rightDiffDetail.setContent(rightContents.get(i - 1));
					rightDiffDetail.setLineNumber(i);
					rightDiffDetail.setType(1);
					rightDiffDetails.add(rightDiffDetail);
				}

			}

		}

		diffentInfomation.setLeftDiffDetails(leftDiffDetails.toArray(new DiffDetail[leftDiffDetails.size()]));

		diffentInfomation.setRightDiffDetails(rightDiffDetails.toArray(new DiffDetail[rightDiffDetails.size()]));

		return diffentInfomation;
	}

	protected ByteArrayOutputStream read(String filePath, String revision, Git git) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		Repository repository = null;
		try {
			// gitDir表示git库目录
			// Git git = Git.open(new File("gitProject"));
			repository = git.getRepository();
			RevWalk walk = new RevWalk(repository);
			ObjectId objId = repository.resolve(revision);
			RevCommit revCommit = walk.parseCommit(objId);
			RevTree revTree = revCommit.getTree();

			// child表示相对git库的文件路径
			TreeWalk treeWalk = TreeWalk.forPath(repository, filePath, revTree);
			ObjectId blobId = treeWalk.getObjectId(0);
			ObjectLoader loader = repository.open(blobId);
			loader.copyTo(out);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JGitInternalException e) {
			e.printStackTrace();
		} finally {
			if (repository != null)
				repository.close();
		}
		return out;
	}

	private static AbstractTreeIterator prepareTreeParser(Repository repository, ObjectId objectId) throws IOException {
		// from the commit we can build the tree which allows us to construct the
		// TreeParser
		// noinspection Duplicates
		try (RevWalk walk = new RevWalk(repository)) {
			RevCommit commit = walk.parseCommit(objectId);
			RevTree tree = walk.parseTree(commit.getTree().getId());

			CanonicalTreeParser treeParser = new CanonicalTreeParser();
			try (ObjectReader reader = repository.newObjectReader()) {
				treeParser.reset(reader, tree.getId());
			}

			walk.dispose();

			return treeParser;
		}
	}

	private String getFilePath(File rootDir, File file) {
		return StringUtils.substringAfter(file.getPath(), rootDir.getPath() + File.separator);
	}

	@Override
	public Map<String, VersionInfo> getResourceVersionInfos(File rootDir, File[] files) throws Exception {

		final Map<String, VersionInfo> map = new HashMap<String, VersionInfo>();

		Git git = Git.open(rootDir);

		for (int i = 0; i < files.length; i++) {

			Iterable<RevCommit> logs = git.log().addPath(getFilePath(rootDir, files[i])).call();

			for (RevCommit rev : logs) {
				VersionInfo versionInfo = new VersionInfo();

				versionInfo.setFileName(files[i].getName());
				versionInfo.setLastCommitAuthor(rev.getCommitterIdent().getName());
				versionInfo.setRevision(rev.getName());
				versionInfo.setServerType(SCMServerBean.GIT_SERVER);
				versionInfo.setTimestamp(rev.getCommitterIdent().getWhen());

				map.put(versionInfo.getFileName(), versionInfo);
				break;
			}
		}

		return map;
	}

	public String getGitUrl(ModuleInfoBean moduleInfo) throws Exception {
		// ssh://<user>:<pwd>@<host>:22/<path-to-remote-repo>/
		StringBuffer url = new StringBuffer();

		SCMServerBean scmServerBean = getScmServerBean();

		url.append(scmServerBean.getProtocol()).append("://");

		if (StringUtils.isNoneBlank(scmServerBean.getUser())) {
			url.append(scmServerBean.getUser()).append(":").append(scmServerBean.getPassword());
			url.append("@");
		}

		url.append(scmServerBean.getHostName());
		if (StringUtils.isNotBlank(scmServerBean.getHostPort())) {
			url.append(":").append(scmServerBean.getHostPort());
		}
		if (StringUtils.startsWith(scmServerBean.getServiceName(), "/")) {
			url.append(scmServerBean.getServiceName());
		} else {
			url.append("/").append(scmServerBean.getServiceName());
		}

		if (moduleInfo != null) {

			if (StringUtils.isNotBlank(moduleInfo.getModule())) {

				if (moduleInfo.getModule().startsWith("/") == false) {
					url.append("/");
				}

				url.append(moduleInfo.getModule());
			}
		}

		return url.toString();
	}

	public static class GITListenerAdapter extends BatchingProgressMonitor {

		private ISCMListener listener;

		public GITListenerAdapter(ISCMListener listener) {
			super();
			this.listener = listener;
		}

		@Override
		protected void onUpdate(String taskName, int workCurr) {
			this.listener.logMessage(taskName + "[" + workCurr + "]");
		}

		@Override
		protected void onEndTask(String taskName, int workCurr) {
			this.listener.logCompleted(taskName);
		}

		@Override
		protected void onUpdate(String taskName, int workCurr, int workTotal, int percentDone) {
			this.listener.onProgress(taskName, workCurr, workTotal);

		}

		@Override
		protected void onEndTask(String taskName, int workCurr, int workTotal, int percentDone) {
			this.listener.logCompleted(taskName);

		}
	}

	public static void main(String[] args) {

		try {

			CredentialsProvider allowHosts = new CredentialsProvider() {

				@Override
				public boolean supports(CredentialItem... items) {
					for (CredentialItem item : items) {
						if ((item instanceof CredentialItem.YesNoType)) {
							return true;
						}
					}
					return false;
				}

				@Override
				public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
					for (CredentialItem item : items) {
						if (item instanceof CredentialItem.YesNoType) {
							((CredentialItem.YesNoType) item).setValue(true);
							return true;
						}
					}
					return false;
				}

				@Override
				public boolean isInteractive() {
					return false;
				}
			};

			String REMOTE_URL = "http://122.112.178.108:8080/scm/git/coe/server/v2.5";

			Git result = Git.cloneRepository().setURI(REMOTE_URL).setDirectory(new File("/Users/qilin/Work/temp"))
					.setCredentialsProvider(new UsernamePasswordCredentialsProvider("coderobot", "Depths123!@#"))
					.call();

			// clean up here to not keep using more and more disk-space for these samples
			// FileUtils.deleteDirectory(localPath);

		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

}
